import allRelationShip, { RelationShip } from './relationShip';

const {
  ME,
  GRANDPARENTS_FATHER,
  GRANDPARENTS_MOTHER,
  FATHER,
  MOTHER,
  AUNT_FATHER,
  UNCLE_FATHER,
  AUNT_MOTHER,
  UNCLE_MOTHER,
  COUSIN_AUNT_FATHER,
  COUSIN_UNCLE_FATHER,
  COUSIN_AUNT_OR_UNCLE_MOTHER,
  COUSIN_UNCLE_MOTHER,
  BROTHER,
  SISTER,
  CHILDREN_BROTHER,
  CHILDREN_SISITER,
  SON,
  DAUGHTER,
  GRANDCHILDREN_SON,
  GRANDCHILDREN_DAUGHTER,
  WIFE_HUSBAND,
  PARENTS_IN_LAW,
  CHILDREN_IN_LAW,
  BROTHER_IN_LAW,
  SISTER_IN_LAW,
  CHILDREN_BROTHER_IN_LAW,
  CHILDREN_SISTER_IN_LAW,
  UNCLE_IN_LAW_FATHER,
  UNCLE_IN_LAW_MOTHER,
  AUNT_IN_LAW_FATHER,
  AUNT_IN_LAW_MOTHER,
  UNCLE_FATHER_OR_FATHER,
  CHILDREN_BROTHER_OR_SON
} = allRelationShip;

// FIXME: b 为分享人，关系列表不全
const RELATIONSHIP_LIST = [
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: FATHER,
    relationShipB2C: SON,

    returnRelationA2C: GRANDCHILDREN_SON,
    returnRelationC2A: GRANDPARENTS_FATHER,
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: MOTHER,
    relationShipB2C: SON,

    returnRelationA2C: GRANDCHILDREN_SON,
    returnRelationC2A: GRANDPARENTS_FATHER,
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: PARENTS_IN_LAW,
    relationShipB2C: CHILDREN_IN_LAW,

    returnRelationA2C: GRANDCHILDREN_DAUGHTER,
    returnRelationC2A: GRANDPARENTS_MOTHER,
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: SISTER,
    relationShipB2C: BROTHER,

    returnRelationA2C: CHILDREN_BROTHER,
    returnRelationC2A: AUNT_FATHER,
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: BROTHER,
    relationShipB2C: BROTHER,

    returnRelationA2C: CHILDREN_BROTHER,
    returnRelationC2A: UNCLE_FATHER,
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: BROTHER_IN_LAW,
    relationShipB2C: BROTHER_IN_LAW,

    returnRelationA2C: CHILDREN_SISITER,
    returnRelationC2A: UNCLE_MOTHER
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: SISTER_IN_LAW,
    relationShipB2C: BROTHER_IN_LAW,

    returnRelationA2C: CHILDREN_SISITER,
    returnRelationC2A: AUNT_MOTHER
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: CHILDREN_SISITER,
    relationShipB2C: UNCLE_MOTHER,

    returnRelationA2C: COUSIN_UNCLE_FATHER,
    returnRelationC2A: COUSIN_AUNT_FATHER,
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: CHILDREN_BROTHER,
    relationShipB2C: UNCLE_FATHER,

    returnRelationA2C: COUSIN_UNCLE_FATHER,
    returnRelationC2A: COUSIN_UNCLE_FATHER
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: SON,
    relationShipB2C: FATHER,

    returnRelationA2C: BROTHER,
    returnRelationC2A: BROTHER,
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: DAUGHTER,
    relationShipB2C: FATHER,

    returnRelationA2C: SISTER,
    returnRelationC2A: BROTHER
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: CHILDREN_BROTHER_IN_LAW,
    relationShipB2C: UNCLE_IN_LAW_FATHER,

    returnRelationA2C: COUSIN_AUNT_FATHER,
    returnRelationC2A: COUSIN_AUNT_OR_UNCLE_MOTHER,
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: CHILDREN_SISTER_IN_LAW,
    relationShipB2C: UNCLE_IN_LAW_FATHER,

    returnRelationA2C: COUSIN_AUNT_FATHER,
    returnRelationC2A: COUSIN_AUNT_OR_UNCLE_MOTHER
  },
  {
    // FIXME: B 是 A 的父亲， B 是 C 的爷爷，C 可能是 A 的儿子，也可能是侄子。
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: GRANDCHILDREN_SON,
    relationShipB2C: GRANDPARENTS_FATHER,

    returnRelationA2C: UNCLE_FATHER_OR_FATHER,
    returnRelationC2A: CHILDREN_BROTHER_OR_SON,
  },
  {
    // FIXME: 问题同上
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: GRANDCHILDREN_DAUGHTER,
    relationShipB2C: GRANDPARENTS_MOTHER,

    returnRelationA2C: UNCLE_MOTHER,
    returnRelationC2A: CHILDREN_SISITER
  },
  {
    relationShipA2B: FATHER,
    relationShipB2A: SON,

    relationShipC2B: BROTHER,
    relationShipB2C: BROTHER,

    returnRelationA2C: FATHER,
    returnRelationC2A: SON
  },
  {
    relationShipA2B: SON,
    relationShipB2A: FATHER,

    relationShipC2B: WIFE_HUSBAND,
    relationShipB2C: WIFE_HUSBAND,

    returnRelationA2C: SON,
    returnRelationC2A: MOTHER
  },
  {
    relationShipA2B: BROTHER,
    relationShipB2A: BROTHER,

    relationShipC2B: CHILDREN_BROTHER,
    relationShipB2C: UNCLE_FATHER,

    returnRelationA2C: UNCLE_FATHER,
    returnRelationC2A: CHILDREN_BROTHER
  },
  {
    relationShipA2B: FATHER,
    relationShipB2A: SON,

    relationShipC2B: CHILDREN_BROTHER,
    relationShipB2C: UNCLE_FATHER,

    returnRelationA2C: GRANDPARENTS_FATHER,
    returnRelationC2A: GRANDCHILDREN_SON
  },
  {
    relationShipA2B: BROTHER,
    relationShipB2A: BROTHER,

    relationShipC2B: BROTHER,
    relationShipB2C: BROTHER,

    returnRelationA2C: BROTHER,
    returnRelationC2A: BROTHER
  },
  {
    relationShipA2B: BROTHER,
    relationShipB2A: BROTHER,

    relationShipC2B: SISTER,
    relationShipB2C: BROTHER,

    returnRelationA2C: BROTHER,
    returnRelationC2A: SISTER
  },
  {
    relationShipA2B: CHILDREN_BROTHER,
    relationShipB2A: UNCLE_FATHER,

    relationShipC2B: SISTER,
    relationShipB2C: BROTHER,

    returnRelationA2C: CHILDREN_BROTHER,
    returnRelationC2A: AUNT_FATHER
  },
  {
    relationShipA2B: FATHER,
    relationShipB2A: SON,

    relationShipC2B: SISTER,
    relationShipB2C: BROTHER,

    returnRelationA2C: FATHER,
    returnRelationC2A: DAUGHTER
  },
  {
    relationShipA2B: GRANDCHILDREN_SON,
    relationShipB2A: GRANDPARENTS_FATHER,

    relationShipC2B: GRANDCHILDREN_SON,
    relationShipB2C: GRANDPARENTS_FATHER,

    returnRelationA2C: BROTHER,
    returnRelationC2A: BROTHER
  }
]

class Person {
  [ME]: string;

  /* 家族树关系 */
  [GRANDPARENTS_FATHER]: string;
  [GRANDPARENTS_MOTHER]: string;

  [FATHER]: string;
  [MOTHER]: string;
  [AUNT_FATHER]: string;
  [UNCLE_FATHER]: string;
  [AUNT_MOTHER]: string;
  [UNCLE_MOTHER]: string;

  [COUSIN_AUNT_FATHER]: string;
  [COUSIN_UNCLE_FATHER]: string;
  [COUSIN_AUNT_OR_UNCLE_MOTHER]: string;
  [COUSIN_UNCLE_MOTHER]: string;
  [BROTHER]: string;
  [SISTER]: string;


  [CHILDREN_BROTHER]: string;
  [CHILDREN_SISITER]: string;
  [SON]: string;
  [DAUGHTER]: string;

  [GRANDCHILDREN_SON]: string;
  [GRANDCHILDREN_DAUGHTER]: string;

   /* 非家族树关系 */
  [WIFE_HUSBAND]: string;
  [PARENTS_IN_LAW]: string;
  [CHILDREN_IN_LAW]: string;
  [BROTHER_IN_LAW]: string;
  [SISTER_IN_LAW]: string;
  [CHILDREN_BROTHER_IN_LAW]: string;
  [CHILDREN_SISTER_IN_LAW]: string;
  [UNCLE_IN_LAW_FATHER]: string;
  [UNCLE_IN_LAW_MOTHER]: string;
  [AUNT_IN_LAW_FATHER]: string;
  [AUNT_IN_LAW_MOTHER]: string;

   /* 存疑关系 */
  [UNCLE_FATHER_OR_FATHER]: string;
  [CHILDREN_BROTHER_OR_SON]: string;

  [Symbol.iterator]() {
    const keys = Object.keys(this) as unknown as (keyof Person)[];
    const keyAndVal: [keyof Person, string][] = [];
    for (let key of keys) {
      keyAndVal.push([key, this[key] as string]);
    }

    let nextIndex = 0;

    return {
      next: () => {
        return nextIndex < keyAndVal.length ?
          { value: keyAndVal[nextIndex++], done: false } :
          { done: true };
      }
    } as {
      next: () => {
        value: [keyof Person, string], done: boolean
      }
    }
  }

  // TODO: 应根据数据库中数据做初始化
  constructor(id: string) {
    this[ME] = id;
  }

  /* 获取 relation 在本人中的亲属关系 */
  getRelationShipByPerson(relation: Person) {
    return this.getRelationShipById(relation[ME]);
  }

  getRelationShipById(this: Person, id: string) {
    for (const [key, val] of this) {
      const ids = val.split(','); // 分割 id

      if (~ids.indexOf(id)) {
        return key;
      }
    }

    return undefined;
  }

  setRelationShip(relation: RelationShip , id: string) {
    // 如果之前有值，则在后面拼接
    if (this[relation]) {
      this[relation] = `${this[relation]},${id}`;
    } else {
      this[relation] = id;
    }
  }

  deleteRelationShip(relation: RelationShip , id: string) {
    this[relation] = this[relation].replace(id, '');
    if (!this[relation]) {
      delete this[relation];
      return undefined
    }
    return this[relation];
  }

  getFamilyTreeId() {
    let tree = {};
    for (let [key, val] of this) {
      // FIXME： 其他不属于家族树的关系都应该剪掉, 可以只遍历自身，这样从根本上解决。
      if (key === 'ME') continue;
      if (key === 'WIFE_HUSBAND') continue;
      tree = {
        ...tree,
        [key]: val,
      }
    }
    return tree;
  }

  /* 通过中间人 mid，获取 自身与 relation 的关系 */
  /* this = a mid = b relation = c */
  getRelationShipByMidPerson(mid: Person, relation: Person) {
    const relationB2A = this.getRelationShipByPerson(mid);
    const relationA2B = mid.getRelationShipByPerson(this);

    const relationB2C = relation.getRelationShipByPerson(mid);
    const relationC2B = mid.getRelationShipByPerson(relation);
    let relationA2C;

    for (const list of RELATIONSHIP_LIST) {
      if (list.relationShipA2B === relationA2B
        && list.relationShipB2A === relationB2A
        && list.relationShipC2B === relationC2B
        && list.relationShipB2C === relationB2C
      ) {
        relationA2C = [list.returnRelationA2C, list.returnRelationC2A];
      }
    }

    return relationA2C;
  }

  getRelationShipByName(relationShip: any) {
    return (this as any)[relationShip];
  }
}

class PersonList {
  [ME]: Person;
  public familyTree: Person[] = [];

  // FIXME: familyTree
  constructor(person: Person, familyTree: Person[]) {
    this[ME] = person;
    this.familyTree = familyTree;
  }


  static personById(list: Person[], id: string) {
    for (const person of list) {
      if (person[ME] === id) {
        return person;
      }
    }

    return undefined;
  }

  // 更新 自身 的家族树中成员与 relation 的关系
  // 自身 = a relation = b
  // 此处只会有 relation 与 person 会发生变化
  updateRelationShip(relation: Person) {
     // 用于保存家族树发生改变的人，用于后续对数据库进行更新。
    let update: any = {
      [relation[ME]]: ''
    };

    for (const person of this.familyTree) {
      const result = person.getRelationShipByMidPerson(this[ME], relation);
      let Person2b;
      let b2Person;
      if (result) {
        b2Person = result[0];
        Person2b = result[1];
      }

      if (Person2b && b2Person && person[ME] !== relation[ME]) {
        person.setRelationShip(Person2b, relation[ME]);
        relation.setRelationShip(b2Person, person[ME]);

        const { [relation[ME]]: relationShip , ...others }  = update;
        let relationResult = '';

        if (relationShip !== '') {
          relationResult = relationShip + '/' + b2Person + ':' +relation.getRelationShipByName(b2Person);
        } else {
          relationResult = b2Person + ':' +relation.getRelationShipByName(b2Person);
        }

        const personResult = Person2b + ':' + person.getRelationShipByName(Person2b);

        update = {
          ...others,
          [relation[ME]]: relationResult,
          [person[ME]]: personResult
        }
      }
    }

    return update;
  }

  deleteRelationShip() {
    let deleteData = {};
    this.familyTree.forEach(person => {
      // 获取要删除的人在他人家族树中的位置
      const name = person.getRelationShipById(this[ME][ME]);
      if (name) {
        const result = person.deleteRelationShip((name as RelationShip), this[ME][ME]);
        deleteData = {
          ...deleteData,
          [person[ME]]: (name as RelationShip) + ':' +result
        }
      }
    }) 

    return deleteData;
  }
}

let son = new Person('1');
son.setRelationShip(FATHER, '2');

let father = new Person('2');
father.setRelationShip(SON, '1');
father.setRelationShip(FATHER, '3');

let grandfather = new Person('3'); // 由 father 分享， father 的爸爸
grandfather.setRelationShip(SON, '2');
let fatherFamilyTree = new PersonList(father, [son, grandfather]);
const result1 = fatherFamilyTree.updateRelationShip(grandfather);

let son2 = new Person('9');
son2.setRelationShip(GRANDPARENTS_FATHER, '3');

grandfather.setRelationShip(GRANDCHILDREN_SON, '9');
let grandfatherTree = new PersonList(grandfather, [son, father]);
const result3 = grandfatherTree.updateRelationShip(son2);
console.log('更新操作：',result3);


let uncle1 = new Person('4'); // 由 father 分享， father 的 哥哥
uncle1.setRelationShip(BROTHER, '2');

father.setRelationShip(BROTHER, '4');
fatherFamilyTree = new PersonList(father, [son, grandfather, uncle1]);
const result2 = fatherFamilyTree.updateRelationShip(uncle1);

let uncle2 = new Person('5') // 由 father 分享， father 的 哥哥
uncle2.setRelationShip(BROTHER, '2');

father.setRelationShip(BROTHER, '5');
fatherFamilyTree = new PersonList(father, [son, grandfather, uncle1, uncle2]);
fatherFamilyTree.updateRelationShip(uncle2);

let wife = new Person('6');  // 由 father 分享， father 的 妻子
wife.setRelationShip(WIFE_HUSBAND, '2');

father.setRelationShip(WIFE_HUSBAND, '6');
fatherFamilyTree.updateRelationShip(wife);

let cousinAuntFather = new Person('7'); // 由 father 分享， father 的 侄子
cousinAuntFather.setRelationShip(UNCLE_FATHER, '2');

father.setRelationShip(CHILDREN_BROTHER, '7');
fatherFamilyTree = new PersonList(father, [son, grandfather, uncle1, uncle2, cousinAuntFather]);
fatherFamilyTree.updateRelationShip(cousinAuntFather);

let aunt = new Person('8'); // 由 uncle1 分享， uncle1 的 姐姐
aunt.setRelationShip(BROTHER, '4');

uncle1.setRelationShip(SISTER, '8')
let uncle1Family = new PersonList(uncle1, [father, uncle2, son, cousinAuntFather, grandfather]);
uncle1Family.updateRelationShip(aunt);

const auntFamilyTree = new PersonList(aunt, [father, uncle1, uncle2, son, cousinAuntFather, grandfather]);
const result4 = auntFamilyTree.deleteRelationShip();
console.log('删除操作：',result4);

console.log(son.getFamilyTreeId(), 'son');
console.log(father.getFamilyTreeId(), 'father')
console.log(grandfather.getFamilyTreeId(), 'grandfather')
console.log(uncle1.getFamilyTreeId(), 'uncle1')
console.log(uncle2.getFamilyTreeId(), 'uncle2')
console.log(wife.getFamilyTreeId(), 'wife')
console.log(cousinAuntFather.getFamilyTreeId(), 'cousin_aunt_father');
console.log(aunt.getFamilyTreeId(), 'aunt');
